<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link rel="Stylesheet" type="text/css" href="doc.css" />
<title>Pruning the Search Tree</title>
</head>
<body>
<h1><a name="top">Pruning the Search Tree</a></h1>
<p>
An EMF dataset is naturally hierarchically structured.  Queries frequently
traverse this tree content in search of objects.  One technique for omptimizing
queries is to detect when a branch of the tree cannot contain positive results,
so that it may be skipped entirely.  This technique is called <i>pruning</i>.
</p>

<h2>Prune Handlers</h2>

<p>
Any <a href="../javadoc/org/eclipse/emf/query/conditions/eobjects/EObjectCondition.html"><em class="CodeName">EObjectCondition</em></a>
can be configured with a
<a href="../javadoc/org/eclipse/emf/query/handlers/PruneHandler.html"><em class="CodeName">PruneHandler</em></a>
that tells the condition when to prune the search tree.  The default prune
handler for a condition is <em class="CodeName">NEVER</em> which, as the name
suggests, never prunes.
</p>

<blockquote>
	<img src="images/prunehandler.png" alt="Prune Handler API"/><br/>
	<font size="-2">[<a target="_blank" href="images/prunehandler.svg">as SVG</a>]</font>
</blockquote>

<p>
A query will check after each object that is encountered, and either accepted
or rejected, whether to prune that object's subtree.
</p>
<pre class="Code">
// search for books by Dickens, only in branches in the west end of the city
// because those are geographically closest

// case-insensitive substring match (hopefully we don't have a Weston Branch East)
final EObjectCondition isWest = new EObjectAttributeValueCondition(
        EXTLibraryPackage.Literals.LIBRARY__NAME,
        new SubStringValue("west", false);

PruneHandler pruner = new PruneHandler() {
        public boolean <b>shouldPrune</b>(EObject object) {
            // any branch not in the west cannot contain branches that are.
            // Also, anything that isn't a library can't contain branches
            return !isWest.isSatisfied(object);
        }};

// look for libraries in the west.  Wrap the condition that we already have
// so that we can apply the prune-handler.  Note that this wrapping is only
// necessary because our prune-handler uses the same condition
EObjectCondition libraryCond = new EObjectConditionAdapter(isWest, <b>pruner</b>);

// find books by Dickens
Writer dickens = getWriter("Charles Dickens");
EObjectCondition bookCond = new EObjectReferenceValueCondition(
        EXTLibraryPackage.Literals.BOOK__AUTHOR, isDickens);

// search from the root of the library hierarchy
Library mainBranch = getMainBranch();

// the nested query with the prune handler gets the western libraries to search
IQueryResult result = new SELECT(
    new FROM(new SELECT(
        new FROM(mainBranch), new WHERE(<b>libraryCond</b>))),
    new WHERE(<b>bookCond</b>)).execute();
</pre>

<hr/>

<p>
<a href="http://www.eclipse.org/legal/epl-v10.html">Copyright (c) 2000, 2007 IBM Corporation and others. All Rights Reserved.</a>
</p>
</body>
</html>
